package com.google.code.sms.ajax;

import com.google.code.sms.domain.MediaElement;
import com.google.code.sms.domain.Player;
import com.google.code.sms.domain.TransferStatus;
import com.google.code.sms.service.MediaElementService;
import com.google.code.sms.service.MediaScannerService;
import com.google.code.sms.service.PlayerService;
import com.google.code.sms.service.SettingsService;
import com.google.code.sms.service.StatusService;
import com.google.code.sms.util.StringUtil;
import org.apache.commons.lang.StringUtils;
import org.directwebremoting.WebContext;
import org.directwebremoting.WebContextFactory;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.util.ArrayList;
import java.util.List;

public class NowPlayingService {

    private PlayerService playerService;
    private StatusService statusService;
    private SettingsService settingsService;
    private MediaScannerService mediaScannerService;
    private MediaElementService mediaElementService;

    /**
     * Returns details about what the current player is playing.
     *
     * @return Details about what the current player is playing,
     * or <code>null</code> if not playing anything.
     */
    public NowPlayingInfo getNowPlayingForCurrentPlayer() throws Exception {
        WebContext webContext = WebContextFactory.get();
        Player player = playerService.getPlayer(webContext.getHttpServletRequest(), webContext.getHttpServletResponse());
        List<TransferStatus> statuses = statusService.getStreamStatusesForPlayer(player);
        List<NowPlayingInfo> result = convert(statuses);

        return result.isEmpty() ? null : result.get(0);
    }

    /**
     * Returns details about what all users are currently playing.
     *
     * @return Details about what all users are currently playing.
     */
    public List<NowPlayingInfo> getNowPlaying() throws Exception {
        return convert(statusService.getAllStreamStatuses());
    }

    /**
     * Returns media folder scanning status.
     */
    public ScanInfo getScanningStatus() {
        return new ScanInfo(mediaScannerService.isScanning(), mediaScannerService.getScanCount());
    }

    private List<NowPlayingInfo> convert(List<TransferStatus> statuses) throws Exception {
        HttpServletRequest request = WebContextFactory.get().getHttpServletRequest();
        String url = request.getRequestURL().toString();
        List<NowPlayingInfo> result = new ArrayList<>();
        
        for (TransferStatus status : statuses) {

            if(status.isActive()) {
                Player player = status.getPlayer();
                File file = status.getFile();

                if (player != null && player.getUsername() != null && file != null)
                {
                    String username = player.getUsername();

                    MediaElement mediaElement = mediaElementService.getMediaElement(file);
                    File coverArt = mediaElementService.getCoverArt(mediaElement);

                    String title = mediaElement.getMetaData().getTitle();
                    
                    // Determine description (e.g. Artist, Parent Directory)
                    String description = "";
                    
                    switch(mediaElement.getMediaElementType())
                    {
                        // For a video element show the parent directory name if it is not the same or similar to the title
                        case VIDEO:
                            
                            if(!mediaElement.getMetaData().getTitle().contains(mediaElement.getParentName()))
                            {
                                description = mediaElement.getParentName();
                            }
                            
                            break;
                           
                        // For an Audio element show the artist or parent directory name
                        case AUDIO:
                            
                            description = mediaElement.getMetaData().getArtist();
                        
                            if(description.equals(""))
                            {
                                description = mediaElement.getParentName();
                            }
                            
                            break;
                            
                        default:
                            break;      
                    }
                    
                    String mediaElementUrl = url.replaceFirst("/dwr/.*", "/main.view?id=" + mediaElement.getId());
                    String streamUrl = url.replaceFirst("/dwr/.*", "/stream?player=" + player.getId() + "&id=" + mediaElement.getId());
                    String coverArtUrl = coverArt == null ? null : url.replaceFirst("/dwr/.*", "/coverArt.view?size=60&id=" + mediaElement.getId());

                    // Rewrite URLs in case we're behind a proxy.
                    if (settingsService.isRewriteUrlEnabled()) {
                        String referer = request.getHeader("referer");
                        mediaElementUrl = StringUtil.rewriteUrl(mediaElementUrl, referer);
                        streamUrl = StringUtil.rewriteUrl(streamUrl, referer);
                        coverArtUrl = StringUtil.rewriteUrl(coverArtUrl, referer);
                    }

                    if (StringUtils.isNotBlank(player.getName())) {
                        username += "@" + player.getName();
                    }
                    title = StringUtil.toHtml(StringUtils.abbreviate(title, 25));
                    description = StringUtil.toHtml(StringUtils.abbreviate(description, 25));
                    username = StringUtil.toHtml(StringUtils.abbreviate(username, 25));

                    result.add(new NowPlayingInfo(username, title, description, streamUrl, mediaElementUrl, coverArtUrl));
                }
            }
        }
            
        return result;
    }

    public void setPlayerService(PlayerService playerService) {
        this.playerService = playerService;
    }

    public void setStatusService(StatusService statusService) {
        this.statusService = statusService;
    }

    public void setSettingsService(SettingsService settingsService) {
        this.settingsService = settingsService;
    }

    public void setMediaScannerService(MediaScannerService mediaScannerService) {
        this.mediaScannerService = mediaScannerService;
    }

    public void setMediaElementService(MediaElementService mediaElementService) {
        this.mediaElementService = mediaElementService;
    }
}
